<html>
<head><meta charset="utf-8"><title>lsp-server framework · t-compiler/rust-analyzer · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/index.html">t-compiler/rust-analyzer</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/lsp-server.20framework.html">lsp-server framework</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="195402565"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/lsp-server%20framework/near/195402565" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Maxim Kurnikov <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/lsp-server.20framework.html#195402565">(Apr 27 2020 at 11:17)</a>:</h4>
<p>Hi. I'm working on a language server for Move language for libra<br>
<a href="https://github.com/libra/libra/tree/master/language/move-lang" title="https://github.com/libra/libra/tree/master/language/move-lang">https://github.com/libra/libra/tree/master/language/move-lang</a><br>
<a href="https://github.com/dfinance/move-language-server" title="https://github.com/dfinance/move-language-server">https://github.com/dfinance/move-language-server</a></p>
<p>I'm using the rust-analyzer code as a reference on how to structure the project and obviously using lsp-server for connections and handshake. I borrowed multithreading architecture / ra_vfs / WorldState concepts too. <br>
I'm wondering, wouldn't it be great to extract more code into lsp-server, make it smth like an lsp-framework? Most of the code in the <code>main_loop</code> could be reused, <code>on_request</code> could be converted into a trait with all those <code>on_completion</code>, <code>on_status_check</code> methods.</p>



<a name="195402709"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/lsp-server%20framework/near/195402709" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/lsp-server.20framework.html#195402709">(Apr 27 2020 at 11:18)</a>:</h4>
<p>I'll reply later today (well, if the amoutn of work I absolutely need to to today is less than today), but you might want to talke a look at tower-lsp-server library as well</p>



<a name="195536081"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/lsp-server%20framework/near/195536081" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/lsp-server.20framework.html#195536081">(Apr 28 2020 at 09:05)</a>:</h4>
<p>So, I thought about extracting lsp-framework a while back, and decided against it, for two reasons, one stupid technical, and one real one. </p>
<p>The technical one is that the framework would have to use <code>lsp_types</code> library, and proper semver versioning of it is complicated (what is semver compatible in TS is breaking in Rust). </p>
<p>The real one is that I think there's a great benefit in running the main event loop yourself. It's a very complicated bit with respect to runtime behavior, so being able to see / dbg! everything yourself is hugely beneficial</p>



<a name="195536131"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/lsp-server%20framework/near/195536131" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/lsp-server.20framework.html#195536131">(Apr 28 2020 at 09:05)</a>:</h4>
<p>that's why lsp-server is designed as a library, and doesn't really do much</p>



<a name="195536277"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/lsp-server%20framework/near/195536277" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/lsp-server.20framework.html#195536277">(Apr 28 2020 at 09:07)</a>:</h4>
<p>The vfs bit could conievably be extracted into a separate library, but unforutantely it's been in a "design is broken, badly needs rewrite" state for about a year now :D</p>



<a name="195536355"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/lsp-server%20framework/near/195536355" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/lsp-server.20framework.html#195536355">(Apr 28 2020 at 09:08)</a>:</h4>
<p>the tower-lsp thing <em>is</em> a framework, so it's a good way to check if my gut feeling about framework vs library here is wrong</p>



<a name="195536858"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/lsp-server%20framework/near/195536858" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Coenen Benjamin <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/lsp-server.20framework.html#195536858">(Apr 28 2020 at 09:13)</a>:</h4>
<p><code>The technical one is that the framework would have to use lsp_types library, and proper semver versioning of it is complicated (what is semver compatible in TS is breaking in Rust).</code> Why not generate either Rust or Ts part to be sure to be sync ? I don't know the context so it could be a dumb question :p</p>



<a name="195537030"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/lsp-server%20framework/near/195537030" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/lsp-server.20framework.html#195537030">(Apr 28 2020 at 09:15)</a>:</h4>
<p>There's no source to generate from :-(</p>
<p>The spec is literally  a markdown document. There's a <code>publish a JSON schema</code> request sitting for ages</p>



<a name="195537186"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/lsp-server%20framework/near/195537186" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Coenen Benjamin <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/lsp-server.20framework.html#195537186">(Apr 28 2020 at 09:17)</a>:</h4>
<p>Oh god :(</p>



<a name="195552484"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/lsp-server%20framework/near/195552484" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Maxim Kurnikov <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/lsp-server.20framework.html#195552484">(Apr 28 2020 at 11:59)</a>:</h4>
<blockquote>
<p>The real one is that I think there's a great benefit in running the main event loop yourself. It's a very complicated bit with respect to runtime behavior, so being able to see / <code>dbg!</code> everything yourself is hugely beneficial</p>
</blockquote>
<p>I don't quite understand this one. While I've been working on move-language-server, I had to reimplement (copy-paste with modifications) lots of code from the rust-analyzer crate in the RA project.</p>
<p>I trust your expertise, so I believe that the current design of lsp server in RA is optimal. It would be great not to reimplement all this stuff for every language server, and just to focus on the relevant parts from the beginning. But if one would like to improve on top of it in any way, it's just the same copy-paste as in the no-framework case.  </p>
<p>Framework lowers barrier to entry, in my opinion.</p>



<a name="195552865"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/lsp-server%20framework/near/195552865" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Maxim Kurnikov <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/lsp-server.20framework.html#195552865">(Apr 28 2020 at 12:03)</a>:</h4>
<p>I've looked at <code>tower-lsp</code>. It's an example of the framework, yes, but it's </p>
<ol>
<li>async-based (which doesn't make much sense in case of lsp, as there's won't be a lot of threads anyway)</li>
<li>it's not tied to rust-analyzer in any way. If the hypothetical <code>lsp-framework</code> could exist, it would be awesome for it to share codebase with rust-analyzer.</li>
</ol>



<a name="195553151"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/lsp-server%20framework/near/195553151" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Maxim Kurnikov <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/lsp-server.20framework.html#195553151">(Apr 28 2020 at 12:05)</a>:</h4>
<p>Thanks for the answers! <br>
And thank you very much for rust-analyzer, it's an amazing tool, I've learn't lots and lots of stuff from the implementation! And thanks for the <a href="https://www.youtube.com/watch?v=Oy_VYovfWyo" title="https://www.youtube.com/watch?v=Oy_VYovfWyo">https://www.youtube.com/watch?v=Oy_VYovfWyo</a> too=)</p>
<div class="youtube-video message_inline_image"><a data-id="Oy_VYovfWyo" href="https://www.youtube.com/watch?v=Oy_VYovfWyo" title="https://www.youtube.com/watch?v=Oy_VYovfWyo"><img src="https://i.ytimg.com/vi/Oy_VYovfWyo/default.jpg"></a></div>



<a name="195641969"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/lsp-server%20framework/near/195641969" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> peter <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/lsp-server.20framework.html#195641969">(Apr 28 2020 at 23:31)</a>:</h4>
<p>if i can ask a silly question, i am looking at setting up a language server and was also looking at lsp-server — when i run this example <a href="https://github.com/rust-analyzer/lsp-server/blob/master/examples/goto_def.rs" title="https://github.com/rust-analyzer/lsp-server/blob/master/examples/goto_def.rs">https://github.com/rust-analyzer/lsp-server/blob/master/examples/goto_def.rs</a>, which sets up a connection over stdio, how do i send a request to the server?</p>
<p>do i just paste e.g. the initialize request listed in the comments in that file, into stdin and hit enter? (when i do that i get a <code>crossbeam::channel::RecvError</code>).</p>



<a name="195946413"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/lsp-server%20framework/near/195946413" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/lsp-server.20framework.html#195946413">(May 01 2020 at 09:58)</a>:</h4>
<p>Driving the server directly from the command line is super painful, as you need correct <code>ContentLenght</code> headers</p>



<a name="195946439"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/lsp-server%20framework/near/195946439" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/lsp-server.20framework.html#195946439">(May 01 2020 at 09:59)</a>:</h4>
<p>The best way is to either drive programmatically via channels, or drive vie some existing client, like VS Code</p>



<a name="195946583"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/lsp-server%20framework/near/195946583" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/lsp-server.20framework.html#195946583">(May 01 2020 at 10:01)</a>:</h4>
<blockquote>
<p>I don't quite understand this one. While I've been working on move-language-server, I had to reimplement (copy-paste with modifications) lots of code from the rust-analyzer crate in the RA project.</p>
</blockquote>
<p><span class="user-mention" data-user-id="222044">@Maxim Kurnikov</span> for example <a href="https://github.com/rust-analyzer/rust-analyzer/blob/a5f2b16366f027ad60c58266a66eb7fbdcbda9f9/crates/rust-analyzer/src/main_loop.rs#L329-L337" title="https://github.com/rust-analyzer/rust-analyzer/blob/a5f2b16366f027ad60c58266a66eb7fbdcbda9f9/crates/rust-analyzer/src/main_loop.rs#L329-L337">here</a> we do some introspection for the single turn of the event loop, which would be awkward to do if the loop was hidden inside the framework</p>



<a name="195946692"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/lsp-server%20framework/near/195946692" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/lsp-server.20framework.html#195946692">(May 01 2020 at 10:02)</a>:</h4>
<p>In general, being able to insert <code>printf</code> into arbitrary state of request processing is something I've found useful</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>